package com.az.miaogateway.filter;

import com.az.jwtcommon.util.JwtTool;
import com.az.miaoapi.dto.UserDto;
import com.az.miaoapi.response.ResponseCode;
import com.az.miaoapi.exception.BaseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Optional;

@Order(1)
@Component
public class JwtGlobalFilter implements GlobalFilter {
    @Value("${jwt.secret}")
    private String secret;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        // 检查请求路径是否包含"/auth"，如果是，则直接执行下一个过滤器
        if (request.getURI().getPath().contains("/auth")) {
            return chain.filter(exchange);
        }
        // 从请求头中获取Authorization令牌
        String token = request.getHeaders().getFirst("Authorization");
        UserDto user;
        try {
            // 从令牌中提取用户ID
            Long userId = JwtTool.getUserIdFromToken(token, secret);
            // 从Redis中获取用户信息，如果不存在则抛出未登录异常
            user = Optional
                    .ofNullable((UserDto) redisTemplate.opsForValue().get("login_users:" + userId))
                    .orElseThrow(() -> new BaseException(ResponseCode.NOT_LOGIN));
            // 使用用户信息重新生成令牌
            token = JwtTool.createUserToken(user, 10L, secret);
            // 设置响应头，表示用户已登录
            exchange.getResponse().getHeaders().add("Login", "TRUE");

        } catch (BaseException e) {
            // 如果发生异常，创建一个默认用户并生成令牌
            user = new UserDto(0L, "guest");
            token = JwtTool.createUserToken(user, secret);
            // 设置响应头，表示用户未登录
            exchange.getResponse().getHeaders().add("Login", "FALSE");
        }
        // 将最终的令牌添加到请求头中
        String finalToken = token;
        ServerHttpRequest serverHttpRequest = request.mutate().headers(h -> h.add("token", finalToken)).build();
        exchange.mutate().request(serverHttpRequest);
        // 打印日志，表示经过JWT全局过滤器
        System.out.println("JwtGlobalFilter");
        // 执行下一个过滤器
        return chain.filter(exchange);
    }
}